from forest.tools.system.mksparse import mksparse
from subprocess import check_output, call, PIPE
from forest.registry import register_tool

# TODO: Sometimes this fails with: http://stackoverflow.com/questions/5881134/cannot-delete-device-dev-loop0

@register_tool('image.LoopDev')
class LoopDev(object):
    ''' An execution context which will create a loop device on enter.
    '''
    def __init__(self, filename, size=None):
        self.filename = filename

        if size:
            mksparse(self.filename, size)

    def __enter__(self):
        self.loopdev = loop_attach(self.filename)
        return self.loopdev

    def __exit__(self, exc_type, exc_value, traceback):
        loop_detach(self.loopdev)


def loop_attach(outfile):
    '''Attach a loop device to the given file. Return the loop device name.
    Raises CalledProcessError if losetup fails.'''
    dev = check_output(["losetup", "--find", "--show", outfile], stderr=PIPE)

    #lint expects dev to be a list here, not string..
    return dev.strip()

def loop_detach(loopdev):
    '''Detach the given loop device. Return False on failure.'''
    call(["losetup", "--detach", loopdev])
    #call(["modprobe","loop"])

